<?php
/**
 * Basic router controller
 *
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 *
 */

/**
 * @namespace
 */
namespace X\Controller;
use X\Loader;

use \X\Controller\Front as FrontController;
use \X\Controller\Response;
use \X\Controller\Response\Standard as StandardResponse;
use \X\Controller\Event;
use \X\Controller;
use \X\Controller\Handler;

use \X\DataStructure\String;

/**
 * simple export controler
 *
 */
class Router implements Controller
{
    /**
     * allow html to hold the place of a contoler action
     *
     * @var bool
     */
    private static $_HtmlFileContent = true;
    /**
     * prefix for handler classes
     *
     * @var string
     */
    protected $_HandlerPrefix = "Handlers\\";
    /**
     * default prefix for renderer classes
     *
     * @var string
     */
    protected $_RendererPrefix = "Renderers\\";
    /**
     * Html file prefix
     * @var string
     */
    protected $_HtmlPrefix = "Html";
    /**
     * State of debugging
     * @var unknown_type
     */
    protected $_Debug = false;
    /**
     * trace of controller debug information
     *
     * @var \X\Logger
     */
    protected $_Logger;
	/**
     * enable debuging mode
     * @return bool
     */
    public function isDebug($Debug = null, \X\Logger $Logger = null)
    {
        // reset debug if it is passed
        if ($Debug !== null)
        {
            $this->_Debug = (bool)$Debug;
        }
        
        // set logger if debug is true
        if ($this->_Debug && !isset($this->_Logger))
        {
            $this->_Logger = ($Logger) ? $Logger : \X\Logger\Memory::getInstance('router');
        }
        
        // return the value of logger
        return $this->_Debug;
    }
	/**
     * log a message
     * @param unknown_type $Message
     * @param unknown_type $Type
     */
    protected function log($Message, $Type = 'general')
    {
        if ($this->_Debug && $this->_Logger) $this->_Logger->logMessage($Message, $Type);
    }
    /**
     * handle input
     *
     * @param X\Controller\Event\Event $Event
     * @param X\Controller\Event\Response $Response
     * @return string|X\Controller\Event\Response
     */
    public function respond(Event $Event = null, Response $Response = null)
    {
        // get the name of the handler for this data
        $StepName = $Event->getStep();
        // give a step if this is the index - use start to
        // avoid including index.php or default.php
        if (empty($StepName)) $StepName = 'index';

        $AppNamespace = FrontController::ApplicationNamespace();
        
        $RoutingGroup = \X\DataStructure\String::toCapWords($StepName);
        $RoutingSubject = \X\DataStructure\String::toCapWords($Event->getStep());

        // then get the event handler name
        $CurrentEventHandler = $AppNamespace . $this->_HandlerPrefix .
                $RoutingGroup . '\\' . $RoutingSubject;
                
        // default rendering to a matching file
        // (the idea is to allow the handler to alter the render name )
        $RendererName = $AppNamespace . $this->_RendererPrefix . $RoutingGroup . '\\' . $RoutingSubject;
        $Response->setRenderName($RendererName);
        

        // if a controller interface, run it that way
        if (\X\Loader::loadClass($CurrentEventHandler, FrontController::getRegistered('controller_path')))
        {
            $EventHandler = new $CurrentEventHandler();
            if ($EventHandler instanceof Handler)
            {
                // create handler instance
                $tmpResponse = $EventHandler->handle($Event, $Response);
                $this->log(__METHOD__. '(' .__LINE__. ") CurrentEventHandler " . $CurrentEventHandler, 'routing');
            }
            else
            {
                //throw new Router\Exception();
                throw new \X\Controller\Exception($CurrentEventHandler . ' is not a instance of Handler');
            }
        }
        elseif (self::$_HtmlFileContent)
        {
            $CombinedName = \implode(' ', $Event->resetPath());
            // build foe file name
            $HtmlFileName = Loader::cleanSlashes(FrontController::getRegistered('controller_path') . $this->_HtmlPrefix . $AppNamespace . String::toCapWords($CombinedName) . '.html');
            if (realpath($HtmlFileName))
            {
                $this->log(__METHOD__. '(' .__LINE__. ") HtmlFileName " .$HtmlFileName, 'routing');
                $tmpResponse = new StandardResponse( file_get_contents($HtmlFileName) );
            }
            else
            {
                throw new \X\Controller\AbsentException(sprintf('unable to route event (%s) or find file content (%s)',
                        $CurrentEventHandler, $HtmlFileName));
            }
        }

        if ($tmpResponse instanceof Response)
        {
            $this->log(__METHOD__. '(' .__LINE__. ") RendererName " . $RendererName, 'routing');
            return $tmpResponse;
        }
        else
        {
            throw new \X\Controller\AbsentException($CurrentEventHandler . ' does not implement interface X\Controller\Response');
        }

        throw new \X\Controller\AbsentException('unable to route event ' . $CurrentEventHandler);
    }
}
